package com.alibaba.citrus.ots.unified.inventory.repository.impl;

import com.alibaba.citrus.ots.common.annotation.EpochTransactional;
import com.alibaba.citrus.ots.common.annotation.RepositoryInvoker;
import com.alibaba.citrus.ots.unified.inventory.facade.service.AllocateApplyOrderWriteServiceImpl;
import com.alibaba.citrus.ots.unified.inventory.repository.AllocateApplyOrderDetailReadRepository;
import com.alibaba.citrus.ots.unified.inventory.repository.AllocateApplyOrderDetailWriteRepository;
import com.alibaba.citrus.ots.unified.inventory.repository.AllocateApplyOrderWriteRepository;
import com.alibaba.citrus.ots.unified.inventory.utils.CodeUtil;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.fastjson.JSONObject;
import com.epoch.app.otsunifiedinventory.domain.allocateapplyorder.dto.CreateAllocateApplyOrderResponse;
import com.epoch.app.otsunifiedinventory.domain.allocateapplyorder.dto.NykCreateAllocateApplyOrderResponse;
import com.epoch.app.otsunifiedinventory.domain.allocateapplyorder.model.AllocateApplyOrder;
import com.epoch.app.otsunifiedinventory.domain.allocateapplyorder.service.AllocateApplyOrderService;
import com.epoch.app.otsunifiedinventory.domain.allocateapplyorderdetail.model.AllocateApplyOrderDetail;
import com.epoch.app.otsunifiedinventory.domain.allocateapplyorderdetail.service.AllocateApplyOrderDetailService;
import com.epoch.app.otsunifiedinventory.sdo.AllocateApplyOrderDetailSDO;
import com.epoch.app.otsunifiedinventory.sdo.AllocateApplyOrderSDO;
import com.epoch.app.otsunifiedinventory.sdo.enums.AllocateApplyOrderStatusEnum;
import com.epoch.app.otsunifiedinventory.sdo.enums.AllocateStatusEnum;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.beans.Transient;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @author heyu
 * @description
 */
@Component
public class AllocateApplyOrderWriteRepositoryImpl implements AllocateApplyOrderWriteRepository {
    private static Log log = Log.getLogger(AllocateApplyOrderWriteRepositoryImpl.class);
    private static final String NULL_STRING = "";
    private static final String REGEX  = "^(0+)";
    @Resource
    private AllocateApplyOrderService allocateApplyOrderService;

    @Resource
    private AllocateApplyOrderDetailService allocateApplyOrderDetailService;

    @Resource
    private AllocateApplyOrderDetailWriteRepository allocateApplyOrderDetailWriteRepository;

    @Resource
    private AllocateApplyOrderDetailReadRepository allocateApplyOrderDetailReadRepository;

    @Override
    @EpochTransactional(appCode="bc_ots", dataSourceCode = "cr_ots", dataSourceType = "app")
    public String createAllocateApplyOrder(AllocateApplyOrderSDO allocateApplyOrderSDO) {
//        UUID uuid = UUID.randomUUID();
        AllocateApplyOrder allocateApplyOrder = new AllocateApplyOrder();
        BeanUtils.copyProperties(allocateApplyOrderSDO,allocateApplyOrder);
        allocateApplyOrder.setCode(CodeUtil.getPSTOCode());
        allocateApplyOrder.setStatus((StringUtils.isBlank(allocateApplyOrderSDO.getFeatures()))?AllocateStatusEnum.DRAFT.getCode():
                AllocateStatusEnum.COMPLETED.getCode());
        allocateApplyOrder.setCreator(allocateApplyOrderSDO.getOperator());
        allocateApplyOrder.setApplyOrgId(allocateApplyOrderSDO.getApplyOrgId());
        log.info("底层插入调拨预报单创建入参："+ JSONObject.toJSONString(allocateApplyOrder));
        allocateApplyOrder.setGmt_create(allocateApplyOrderSDO.getGmtCreate());
        CreateAllocateApplyOrderResponse response = allocateApplyOrderService.createAllocateApplyOrder(allocateApplyOrder);
        if(null==response.getLastInsertId()){
            throw new RuntimeException("调拨预报单插入失败");
        }
        return allocateApplyOrder.getCode();
    }

    @Override
    @RepositoryInvoker
    @EpochTransactional(appCode="bc_ots", dataSourceCode = "cr_ots", dataSourceType = "app")
    public String nykCreateAllocateApplyOrder(AllocateApplyOrderSDO allocateApplyOrderSDO) {
//        UUID uuid = UUID.randomUUID();
        AllocateApplyOrder allocateApplyOrder = new AllocateApplyOrder();
        BeanUtils.copyProperties(allocateApplyOrderSDO,allocateApplyOrder);
        allocateApplyOrder.setCode(CodeUtil.getPSTOCode());
        allocateApplyOrder.setStatus((StringUtils.isBlank(allocateApplyOrderSDO.getFeatures()))?AllocateStatusEnum.DRAFT.getCode():
                AllocateStatusEnum.COMPLETED.getCode());
        allocateApplyOrder.setCreator(allocateApplyOrderSDO.getOperator());
        allocateApplyOrder.setUpdater(allocateApplyOrderSDO.getOperator());
        allocateApplyOrder.setApplyOrgId(allocateApplyOrderSDO.getApplyOrgId());
        log.info("nyk dao create AllocateApplyOrder ："+ JSONObject.toJSONString(allocateApplyOrder));
        allocateApplyOrder.setGmt_create(Objects.isNull(allocateApplyOrderSDO.getGmtCreate())?new Date():allocateApplyOrderSDO.getGmtCreate());
        NykCreateAllocateApplyOrderResponse response = allocateApplyOrderService.nykCreateAllocateApplyOrder(allocateApplyOrder);
        if(Objects.isNull(response) || StringUtils.isBlank(response.getLastInsertId())){
            log.error("AllocateApplyOrderWriteRepositoryImpl.nykCreateAllocateApplyOrder_fail");
            log.error("nykCreateAllocateApplyOrder create fail = allocateApplyOrder {} response {}",allocateApplyOrder,response);
        }
        return allocateApplyOrder.getCode();
    }

    @Override
    @EpochTransactional(appCode="bc_ots", dataSourceCode = "cr_ots", dataSourceType = "app")
    public void updateAllocateApplyOrder(AllocateApplyOrderSDO allocateApplyOrderSDO) {
        AllocateApplyOrder allocateApplyOrder = new AllocateApplyOrder();
        BeanUtils.copyProperties(allocateApplyOrderSDO,allocateApplyOrder);
        allocateApplyOrder.setUpdater(allocateApplyOrderSDO.getOperator());
        //更新调拨预报单
        allocateApplyOrderService.updateAllocateApplyOrder(allocateApplyOrder);
    }

    @Override
    @EpochTransactional(appCode="bc_ots", dataSourceCode = "cr_ots", dataSourceType = "app")
    public void update(AllocateApplyOrderSDO allocateApplyOrderSDO) {
        //更新调拨单
        this.updateAllocateApplyOrder(allocateApplyOrderSDO);
        //删除调拨详情
        allocateApplyOrderDetailWriteRepository.deleteDetailByOrderId(allocateApplyOrderSDO.getId());
        //插入详情
        List<AllocateApplyOrderDetailSDO> list = allocateApplyOrderSDO.getList();
        for (AllocateApplyOrderDetailSDO allocateApplyOrderDetailSDO:list){
            allocateApplyOrderDetailSDO.setIsDTC(Objects.isNull(allocateApplyOrderSDO.getIsDTC())?false:allocateApplyOrderSDO.getIsDTC());
            allocateApplyOrderDetailWriteRepository.createAllocateApplyOrderDetail(allocateApplyOrderDetailSDO);
        }
    }

    @Override
    @EpochTransactional(appCode="bc_ots", dataSourceCode = "cr_ots", dataSourceType = "app")
    public void sapCreate(AllocateApplyOrderSDO allocateApplyOrderSDO) {
        //更新主单
        this.updateAllocateApplyOrder(allocateApplyOrderSDO);
        //插入详情
        List<AllocateApplyOrderDetailSDO> list = allocateApplyOrderSDO.getList();
        Integer lineNo = 1;
        for (AllocateApplyOrderDetailSDO allocateApplyOrderDetailSDO :list){
            BigDecimal unitPrice = allocateApplyOrderDetailSDO.getUnitPrice();
            if (Objects.nonNull(unitPrice)){
                unitPrice = unitPrice.setScale(2, RoundingMode.HALF_UP);
            }
            AllocateApplyOrderDetailSDO allocateApplyOrderDetail = new AllocateApplyOrderDetailSDO();
            BeanUtils.copyProperties(allocateApplyOrderDetailSDO,allocateApplyOrderDetail);
            allocateApplyOrderDetail.setLineNo(lineNo);
            allocateApplyOrderDetail.setAllocateApplyOrderId(allocateApplyOrderSDO.getId().intValue());
            allocateApplyOrderDetail.setApplyQuantity(allocateApplyOrderDetailSDO.getApplyQuantity());
            allocateApplyOrderDetail.setUnitPrice(unitPrice);
            allocateApplyOrderDetail.setSubtotalMoney(allocateApplyOrderDetailSDO.getSubtotalMoney());
            allocateApplyOrderDetail.setCloseCode(allocateApplyOrderDetailSDO.getCloseCode());
            allocateApplyOrderDetail.setCloseReason(allocateApplyOrderDetailSDO.getCloseReason());
            if (AllocateApplyOrderStatusEnum.TO_BE_SUBMITTED.getCode().equals(allocateApplyOrderDetailSDO.getStatus())){
                allocateApplyOrderDetail.setStatus(AllocateApplyOrderStatusEnum.WAIT_ANSWER.getCode());
            }else{
                allocateApplyOrderDetail.setStatus(allocateApplyOrderDetailSDO.getStatus());
            }
            allocateApplyOrderDetail.setAllocateApplyOrderId(allocateApplyOrderSDO.getId().intValue());
            allocateApplyOrderDetail.setOutLineNo(allocateApplyOrderDetailSDO.getOutLineNo());
            allocateApplyOrderDetail.setIsDTC(Objects.isNull(allocateApplyOrderSDO.getIsDTC())?false:allocateApplyOrderSDO.getIsDTC());
            lineNo = lineNo+1;
            allocateApplyOrderDetailWriteRepository.createAllocateApplyOrderDetail(allocateApplyOrderDetail);
        }
    }

    @Override
    @EpochTransactional(appCode="bc_ots", dataSourceCode = "cr_ots", dataSourceType = "app")
    public void sapUpdate(AllocateApplyOrderSDO allocateApplyOrderSDO) {
        //查找明细
        List<AllocateApplyOrderDetail> result = allocateApplyOrderDetailReadRepository.queryDetailByOrderId(allocateApplyOrderSDO.getId());
        Map<String,AllocateApplyOrderDetail> allocateApplyOrderGoodsDetailDTOMap = new HashMap<>();

        Integer lineNoMax =0;
        if (CollectionUtils.isNotEmpty(result)) {
            lineNoMax=result.stream().mapToInt(AllocateApplyOrderDetail::getLineNo).max().getAsInt();
            for (AllocateApplyOrderDetail allocateApplyOrderDetail : result) {
                allocateApplyOrderGoodsDetailDTOMap.put(allocateApplyOrderDetail.getGoodsCode(), allocateApplyOrderDetail);

            }
        }
        //删除明细
        //删除调拨详情
        allocateApplyOrderDetailWriteRepository.deleteDetailByOrderId(allocateApplyOrderSDO.getId());
        //插入详情
        List<AllocateApplyOrderDetailSDO> list = allocateApplyOrderSDO.getList();

        boolean isStatus = true;
        boolean isClosed = true;
        for (AllocateApplyOrderDetailSDO allocateApplyOrderDetailSDO :list){
            AllocateApplyOrderDetail allocateApplyOrderDetailOld = allocateApplyOrderGoodsDetailDTOMap.get(allocateApplyOrderDetailSDO.getScItemId().replaceAll(REGEX, NULL_STRING));
            BigDecimal unitPrice = allocateApplyOrderDetailSDO.getUnitPrice();
            if (Objects.nonNull(unitPrice)){
                unitPrice = unitPrice.setScale(2, RoundingMode.HALF_UP);
            }
            AllocateApplyOrderDetailSDO allocateApplyOrderDetail = new AllocateApplyOrderDetailSDO();
            if (Objects.isNull(allocateApplyOrderDetailOld)){
                BeanUtils.copyProperties(allocateApplyOrderDetailSDO,allocateApplyOrderDetail);
                allocateApplyOrderDetail.setLineNo(lineNoMax +1);
                allocateApplyOrderDetail.setAllocateApplyOrderId(allocateApplyOrderSDO.getId().intValue());
                allocateApplyOrderDetail.setApplyQuantity(allocateApplyOrderDetailSDO.getApplyQuantity());
                allocateApplyOrderDetail.setUnitPrice(unitPrice);
                allocateApplyOrderDetail.setSubtotalMoney(allocateApplyOrderDetailSDO.getSubtotalMoney());
                allocateApplyOrderDetail.setCloseReason(allocateApplyOrderDetailSDO.getCloseCode());
                if (StringUtils.isNotEmpty(allocateApplyOrderDetailSDO.getCloseCode())){
                    allocateApplyOrderDetail.setStatus(AllocateApplyOrderStatusEnum.CLOSED.getCode());
                }else{
                    allocateApplyOrderDetail.setStatus(allocateApplyOrderDetailSDO.getStatus());
                }
                allocateApplyOrderDetail.setAllocateApplyOrderId(allocateApplyOrderSDO.getId().intValue());
                allocateApplyOrderDetail.setOutLineNo(allocateApplyOrderDetailSDO.getOutLineNo());
                allocateApplyOrderDetail.setIsDTC(Objects.isNull(allocateApplyOrderSDO.getIsDTC())?false:allocateApplyOrderSDO.getIsDTC());
                lineNoMax++;
            }else{
                BeanUtils.copyProperties(allocateApplyOrderDetailOld,allocateApplyOrderDetail);
                allocateApplyOrderDetail.setScItemId(allocateApplyOrderDetailOld.getGoodsCode());
                allocateApplyOrderDetail.setTitle(allocateApplyOrderDetailOld.getGoodsName());
                allocateApplyOrderDetail.setApplyQuantity(allocateApplyOrderDetailSDO.getApplyQuantity());
                allocateApplyOrderDetail.setUnitPrice(unitPrice);
                allocateApplyOrderDetail.setSubtotalMoney(allocateApplyOrderDetailSDO.getSubtotalMoney());
                if (StringUtils.isNotEmpty(allocateApplyOrderDetailSDO.getCloseCode())){
                    allocateApplyOrderDetail.setStatus(AllocateApplyOrderStatusEnum.CLOSED.getCode());
                }
                allocateApplyOrderDetail.setCloseReason(allocateApplyOrderDetailSDO.getCloseCode());
                allocateApplyOrderDetail.setAllocateApplyOrderId(allocateApplyOrderSDO.getId().intValue());
                allocateApplyOrderDetail.setOutLineNo(allocateApplyOrderDetailSDO.getOutLineNo());
                allocateApplyOrderDetail.setIsDTC(Objects.isNull(allocateApplyOrderSDO.getIsDTC())?false:allocateApplyOrderSDO.getIsDTC());
                if (StringUtils.isNotEmpty(allocateApplyOrderDetailSDO.getRemark())){
                    allocateApplyOrderDetail.setRemark(allocateApplyOrderDetailSDO.getRemark());
                }
                if (Objects.nonNull(allocateApplyOrderDetailSDO.getCloseCode())&&Objects.nonNull(allocateApplyOrderDetailSDO.getCloseReason())){
                    allocateApplyOrderDetail.setIsClosed(1);
                }
            }
            if (!(AllocateApplyOrderStatusEnum.COMPLETED.getCode().equals(allocateApplyOrderDetail.getStatus())
                    ||AllocateApplyOrderStatusEnum.CLOSED.getCode().equals(allocateApplyOrderDetail.getStatus()))){
                isStatus = false;
            }
            if (!AllocateApplyOrderStatusEnum.CLOSED.getCode().equals(allocateApplyOrderDetail.getStatus())){
                isClosed = false;
            }
            allocateApplyOrderDetailWriteRepository.createAllocateApplyOrderDetail(allocateApplyOrderDetail);
        }
        if (isStatus){
            if (isClosed){
                allocateApplyOrderSDO.setStatus(AllocateApplyOrderStatusEnum.CLOSED.getCode());
            }else{
                allocateApplyOrderSDO.setStatus(AllocateApplyOrderStatusEnum.COMPLETED.getCode());
            }
        }
        //更新调拨单
        allocateApplyOrderSDO.setGmt_modified(new Date());
        this.updateAllocateApplyOrder(allocateApplyOrderSDO);
    }

    @Override
    @EpochTransactional(appCode="bc_ots", dataSourceCode = "cr_ots", dataSourceType = "app")
    public void cancel(AllocateApplyOrderSDO allocateApplyOrderSDO) {
        //更新调拨单
        this.updateAllocateApplyOrder(allocateApplyOrderSDO);
        if (Objects.nonNull(allocateApplyOrderSDO.getList())){
            //删除调拨详情
            allocateApplyOrderDetailWriteRepository.deleteDetailByOrderId(allocateApplyOrderSDO.getId());
            //插入详情
            List<AllocateApplyOrderDetailSDO> list = allocateApplyOrderSDO.getList();
            if (CollectionUtils.isNotEmpty(list)){
                for (AllocateApplyOrderDetailSDO allocateApplyOrderDetailSDO:list){
                    allocateApplyOrderDetailSDO.setIsDTC(Objects.isNull(allocateApplyOrderSDO.getIsDTC())?false:allocateApplyOrderSDO.getIsDTC());
                    allocateApplyOrderDetailWriteRepository.createAllocateApplyOrderDetail(allocateApplyOrderDetailSDO);
                }
            }
        }
    }
}
